3.1 短小
- 一个函数最多不要超过
20
行,每行不应该有150
个字符那么长 - 代码块和缩进
if,else,while
其中的代码块应该只有一行,该行应该是一个函数调用语句。
3.2 只做一件事
- 方法一:如果函数只是做了该函数名下同一抽象层上的步骤,则函数只做了一件事。
- 方法二:看能否再拆出一个函数,该函数不仅只是单纯的重现诠释其实现
3.3 每个函数一个抽象层级
自顶向下读代码:向下规则
例如:
把大象装进冰箱里的程序。
主函数层是这样几步:
- 把冰箱门打开;
- 把大象装进去;
- 把冰箱门关上。
其中引用了三个函数,拿函数 1.“把冰箱门打开”来看又细分为如下步骤:
- 找到门把手;
- 判断把手的触发类型;
- 将门把手调整为开门状态;
- 判断门是朝哪个方向开;
- 打开门(返回)。
3.4 switch 语句
写出短小的switch,if/else
语句很难,因为天生要做大于 2 件事。不过我们可以都在同一抽象层级来做事,而且不会重复。
- 我们可以利用多态来实现:利用工厂
将创建对象的逻辑放到工厂里面,隐藏具体实现细节
3.5 使用描述性的名称
- 别害怕长名称,长而具有描述性的名称,要比短而令人费解的名称好。
- 使用某种命名约定,让函数名称中的多个单词容易阅读
- 别害怕花时间取名字。可以尝试不同的名称,测试其阅读效果。使用现代的 IDE 改名字非常简单,想到好名字就改掉
- 命名方式要保持一致。使用与模块名相同的短语、名词、动词给函数命名。如:
includeSetup,includeSetupPages,inludeSuiteSetup
3.6 函数参数
最理想的参数数量是零,其次是一、再其次是二。尽量避免三个或以上的参数
1. 一个函数的普遍形式
2. Boolean 参数
Boolean 参数丑陋不堪,如render(isSuite:bool)
应该讲函数一份为二:renderForSuite()
和renderForSigle
3. 二个参数
- 两个参数要比一个参数难懂。 如:
writeFile(name)
比writeFile(outStream,name)
- 当然有的时候两个参数正好。如:
new Point(0,0)
- 二个参数不算恶劣。但是你可以尽量写成一个参数。如将
writeFile(outStream,name)
,作为成员变量,outStream.writeFile(name)
。还可以分离出新类。
4. 三个参数
有三个参数的函数要比两个参数难懂的多。比如:assertEquals(msg,expected,acture)
,总不能做到第一时间理解。
5. 参数对象
从参数创建对象,从而减少参数数量看起来像是作弊。但是当一组参数被共同传递。就像x和y一样。往往就是有自己名称概念的一部分。
6.参数列表
String.format("%s %.2f",name,hours)
其实和上面的参数对象一样。
7.动词与关键字
- 函数和参数应当是一种非常好的 “动词/名词形式” 比如:
write(name)
. assertEqual
改成assertExpectedEqualsActural()
可能会好些,大大减轻了记忆参数顺序的负担
7.无副作用
- 副作用是一种谎言,函数承诺做一件事,但是还是会做其他被隐藏的事。
- 如果有副作用,那么方法名要包含副作用
1 | checkPassword(name,psw){ |
8.分割指令与询问
函数要么做什么事,要么回答什么事。
1 | if(set("username","jerry")){//考虑下,这里是什么意思?看起来不清晰。到底是检查已经设置为jerry了?还是是否设置成功呢? |
9 使用异常代替返回错误码
- 指令式错误码轻微违反了指令与询问分隔的规则。
- 它鼓励了在 if 语句判断中把指令当表达式来用。
会导致更深的层次嵌套。
1 | if(deletePage(page) == E_OK){ |
9.1 抽离 Try/Catch 代码块
1 | try{ |
9.2 错误处理就是一件事
- 意味着如果 try 开头,就应该是函数内容的第一个单词。
catch/finally{}
后面也不应该有内容
9.3 Error.java 依赖磁铁
建议我们使用异常代替错误码
10 别重复自己
重复是一切邪恶的根源。许多原则和实践规则都是为了消除重复。
12 如何写出这样的函数?
- 写代码和写文章一样,想到什么就写什么。然后再打磨它。
- 没有人能够一次性写好,然后我们一步一步打磨:分解函数、修改名称、消除重复…
小结
- 大师级程序员把系统当做故事来讲,而不是当做程序来写。
- 本章讲的是编写良好的函数机制。如果遵循规则,函数就会短小,有个好名字。
- 不过永远不要忘记真正的目标在于讲述系统的故事。而你编写的函数必须干净利落的拼装到一起,形成一种精确而清晰的语言,帮助你讲故事。